#include "STA_interface.h"
#include <ctime>

#include <iostream>
#include "Route.h"
#include "contest_dm.h"
#include "contest_util.h"
#include "idm.h"
#include <stdexcept>

namespace ieda_contest {

myContestEvaluation::myContestEvaluation(ContestDataManager* data_manager)
{
  /**
   * GCell在每个轴上是均匀的
   * instance的GCell坐标：instance的bounding_box中点的Gcell坐标
   */
  _data_manager = data_manager;
  makeLayerInfo();
  makeGCellInfo();
  makeInstanceList();
  makeNetList();
  // add more
  makeRelativeNetsMap();
  makeGridList();
}

void myContestEvaluation::makeLayerInfo()
{
  std::map<std::string, int>& layer_name_to_idx_map = _data_manager->get_database()->get_layer_name_to_idx_map();
  std::map<int, std::string>& layer_idx_to_name_map = _data_manager->get_database()->get_layer_idx_to_name_map();
  std::map<int, idb::IdbLayerDirection>& layer_idx_to_direction_map = _data_manager->get_database()->get_layer_idx_to_direction_map();

  int layer_idx = 0;
  for (idb::IdbLayer* idb_layer : _data_manager->get_idb_layout()->get_layers()->get_layers()) {
    if (idb_layer->is_routing()) {
      idb::IdbLayerRouting* idb_routing_layer = dynamic_cast<idb::IdbLayerRouting*>(idb_layer);
      // 如果是路由图层，则将其强制转换为 idb::IdbLayerRouting 类型，以便访问路由图层的属性。
      layer_name_to_idx_map[idb_routing_layer->get_name()] = layer_idx;
      layer_idx_to_name_map[layer_idx] = idb_routing_layer->get_name();
      layer_idx_to_direction_map[layer_idx] = idb_routing_layer->get_direction();
      layer_idx++;
    }
  }
}

void myContestEvaluation::makeGCellInfo()
{
  std::map<std::string, int>& layer_name_to_idx_map = _data_manager->get_database()->get_layer_name_to_idx_map();

  std::set<int> single_gcell_x_span_set;
  std::set<int> single_gcell_y_span_set;
  for (idb::IdbGCellGrid* idb_gcell_grid : _data_manager->get_idb_layout()->get_gcell_grid_list()->get_gcell_grid_list()) {
    if (idb_gcell_grid->get_direction() == idb::IdbTrackDirection::kDirectionX) {
      single_gcell_x_span_set.insert(idb_gcell_grid->get_space());
    } else if (idb_gcell_grid->get_direction() == idb::IdbTrackDirection::kDirectionY) {
      single_gcell_y_span_set.insert(idb_gcell_grid->get_space());
    } else {
      std::cout << "[error] The direction of gcell grid is invaild!" << std::endl;
      exit(1);
    }
  }
  if (single_gcell_x_span_set.size() == 0) {
    std::cout << "[error] The x_gcell_grid is empty!" << std::endl;
    exit(1);
  }
  if (single_gcell_y_span_set.size() == 0) {
    std::cout << "[error] The y_gcell_grid is empty!" << std::endl;
    exit(1);
  }
  if (single_gcell_x_span_set.size() > 1) {
    std::cout << "[error] The x_gcell_grid is uneven!" << std::endl;
    exit(1);
  }
  if (single_gcell_y_span_set.size() > 1) {
    std::cout << "[error] The y_gcell_grid is uneven!" << std::endl;
    exit(1);
  }
  int single_gcell_x_span = *single_gcell_x_span_set.begin();
  int single_gcell_y_span = *single_gcell_y_span_set.begin();
  /**
   * single_gcell_x_span
   * single_gcell_y_span
   * single_gcell_area
   */
  _data_manager->get_database()->set_single_gcell_x_span(single_gcell_x_span);
  _data_manager->get_database()->set_single_gcell_y_span(single_gcell_y_span);
  _data_manager->get_database()->set_single_gcell_area(single_gcell_x_span * single_gcell_y_span);
  // layer_gcell_supply_map
  // 根据每个图层的布线方向和 GCell 网格的偏好间距计算供应量。
  std::map<int, int>& layer_gcell_supply_map = _data_manager->get_database()->get_layer_gcell_supply_map();
  for (idb::IdbLayer* idb_layer : _data_manager->get_idb_layout()->get_layers()->get_layers()) {
    if (idb_layer->is_routing()) {
      idb::IdbLayerRouting* idb_routing_layer = dynamic_cast<idb::IdbLayerRouting*>(idb_layer);

      int prefer_pitch = 0;
      for (idb::IdbTrackGrid* idb_track_grid : idb_routing_layer->get_track_grid_list()) {
        idb::IdbTrack* idb_track = idb_track_grid->get_track();

        if (idb_routing_layer->get_direction() == idb::IdbLayerDirection::kHorizontal
            && idb_track->get_direction() == idb::IdbTrackDirection::kDirectionY) {
          prefer_pitch = idb_track->get_pitch();
        } else if (idb_routing_layer->get_direction() == idb::IdbLayerDirection::kVertical
                   && idb_track->get_direction() == idb::IdbTrackDirection::kDirectionX) {
          prefer_pitch = idb_track->get_pitch();
        }
      }
      if (idb_routing_layer->get_direction() == idb::IdbLayerDirection::kHorizontal) {
        layer_gcell_supply_map[layer_name_to_idx_map[idb_routing_layer->get_name()]] = (single_gcell_y_span / prefer_pitch);
        // 如果图层方向为水平且轨迹方向为垂直，则 GCell 供应量为垂直方向上单个 GCell 网格跨度除以轨迹的偏好间距。
      } else if (idb_routing_layer->get_direction() == idb::IdbLayerDirection::kVertical) {
        layer_gcell_supply_map[layer_name_to_idx_map[idb_routing_layer->get_name()]] = (single_gcell_x_span / prefer_pitch);
      }
    }
  }
}

void myContestEvaluation::makeInstanceList()
{
  std::vector<ContestInstance>& contest_instance_list = _data_manager->get_database()->get_instance_list();

  for (idb::IdbInstance* idb_instance : _data_manager->get_idb_design()->get_instance_list()->get_instance_list()) {
    ContestCoord coord(idb_instance->get_bounding_box()->get_middle_point_x(), idb_instance->get_bounding_box()->get_middle_point_y(), 0);

    ContestInstance contest_instance;
    contest_instance.set_name(idb_instance->get_name());
    contest_instance.set_real_coord(coord);
    contest_instance.set_grid_coord(getGCellCoord(coord));
    contest_instance.set_area(idb_instance->get_cell_master()->get_width() * idb_instance->get_cell_master()->get_height());
    contest_instance_list.push_back(contest_instance);
  }
}

ContestCoord myContestEvaluation::getGCellCoord(const ContestCoord& coord)
{
  int single_gcell_x_span = _data_manager->get_database()->get_single_gcell_x_span();
  int single_gcell_y_span = _data_manager->get_database()->get_single_gcell_y_span();

  ContestCoord gcell_coord;
  gcell_coord.set_x((coord.get_x() > 0 ? coord.get_x() - 1 : coord.get_x()) / single_gcell_x_span);
  gcell_coord.set_y((coord.get_y() > 0 ? coord.get_y() - 1 : coord.get_y()) / single_gcell_y_span);
  gcell_coord.set_layer_idx(coord.get_layer_idx());
  return gcell_coord;
}

void myContestEvaluation::makeNetList()
{
  // 建立一个net name到net id的map
  std::map<std::string, int>& layer_name_to_idx_map = _data_manager->get_database()->get_layer_name_to_idx_map();

  // 抽取gcell的x和y跨度
  int single_gcell_x_span = _data_manager->get_database()->get_single_gcell_x_span();
  int single_gcell_y_span = _data_manager->get_database()->get_single_gcell_y_span();

  // 在net类中构造pin list
  for (ContestNet& contest_net : _data_manager->get_database()->get_net_list()) {
    idb::IdbNet* idb_net = _data_manager->get_idb_design()->get_net_list()->find_net(contest_net.get_net_name());
    // pin_list
    std::vector<ContestPin>& pin_list = contest_net.get_pin_list();
    for (idb::IdbPin* idb_pin : idb_net->get_instance_pin_list()->get_pin_list()) {
      ContestCoord coord(idb_pin->get_instance()->get_bounding_box()->get_middle_point_x(),
                         idb_pin->get_instance()->get_bounding_box()->get_middle_point_y(), 0);

      ContestPin contest_pin;
      contest_pin.set_real_coord(coord);
      contest_pin.set_grid_coord(getGCellCoord(coord));
      contest_pin.get_contained_instance_list().push_back(idb_pin->get_instance()->get_name());
      contest_pin.get_contained_pin_list().push_back(std::string(idb_pin->get_instance()->get_name() + ":" + idb_pin->get_pin_name()));
      // add more
      // 将IdbPin获得的IdbInstance，复制一份到contest_pin。
      contest_pin.set_instance(idb_pin->get_instance());
      pin_list.push_back(contest_pin);
    }
    if (idb_net->get_io_pin() != nullptr) {
      idb::IdbPin* io_pin = idb_net->get_io_pin();
      ContestCoord coord(io_pin->get_bounding_box()->get_middle_point_x(), io_pin->get_bounding_box()->get_middle_point_y(), 0);

      ContestPin contest_pin;
      contest_pin.set_real_coord(coord);
      contest_pin.set_grid_coord(getGCellCoord(coord));
      contest_pin.get_contained_instance_list().push_back("io_pin");
      contest_pin.get_contained_pin_list().push_back(io_pin->get_pin_name());
      pin_list.push_back(contest_pin);
    }

    // 在net类中构造routing_segment_list，下面分析具体的构造流程。因此这是针对一条net
    // a. 构造一个map，key是一个pair，value是一个set
    std::map<std::pair<int, int>, std::set<int>> planar_layer_map;

    // b. 遍历net中的每一个guide
    for (ContestGuide& contest_guide : contest_net.get_guide_list()) {

      // c. 获取这一条guide对应的layer id
      int layer_idx = layer_name_to_idx_map[contest_guide.get_layer_name()];

      // d. 获取guide所在gcell的左下角中心真实坐标和右上角中心真实坐标
      ContestCoord real_lb_coord(contest_guide.get_lb_x() + (single_gcell_x_span / 2), contest_guide.get_lb_y() + (single_gcell_y_span / 2),
                                 layer_idx);
      ContestCoord real_rt_coord(contest_guide.get_rt_x() - (single_gcell_x_span / 2), contest_guide.get_rt_y() - (single_gcell_y_span / 2),
                                 layer_idx);
      // e. 获取对应的网格坐标
      ContestCoord grid_lb_coord = getGCellCoord(real_lb_coord);
      ContestCoord grid_rt_coord = getGCellCoord(real_rt_coord);

      // f. 建立xy的pair，左下角和右上角
      std::pair<int, int> lb_planar_coord(grid_lb_coord.get_x(), grid_lb_coord.get_y());
      std::pair<int, int> rt_planar_coord(grid_rt_coord.get_x(), grid_rt_coord.get_y());

      // g. 将获取的信息放到map中去，planar_layer_map中的每一个值，first对应了网格坐标，second对应layer index

      // case1: 由于map中采用了坐标作为key，同时map要求key是唯一的，并且set本身只储存唯一的数据，
      // 因此如果有两个坐标点相同，且位于同一个layer，那么在planar_layer_map中只显示一组信息。

      // case2: 如果两个坐标点相同，且位于不同的layer，那么set的insert方法会在planar_layer_map的second中增加额外的维度

      // example，网格点x1和y1经过了layer1和layer2，那么planar_layer_map的fisrt变量是x1和y1，second变量是layer1和layer2
      planar_layer_map[lb_planar_coord].insert(layer_idx); // insert是对应set的语法
      planar_layer_map[rt_planar_coord].insert(layer_idx);
    }

    // 上面的循环建立了一个planar_layer_map，接下来把case1中的情况删除，即删除layer只有一层的
    // h. 建立一个中间变量，储存待删除的坐标，也就是map中的key
    std::set<std::pair<int, int>> remove_key_set;
    for (auto& [planar_coord, layer_set] : planar_layer_map) {
      // i. 如果坐标对应的layer只有一层，则储存进remove_key_set中，随后再通过一个for loop删除
      if (layer_set.size() == 1) {
        remove_key_set.insert(planar_coord);
      }
    }
    for (const auto& key : remove_key_set) {
      planar_layer_map.erase(key);
    }
    /////////////////////////////////////////////
    // 因为guide是二维布线，因此经过上面的步骤，现在的planar_layer_map中储存了所有同坐标但是跨layer的走线
    // 也就是储存了所有的via，接下来需要加入同一层的布线信息

    // j. 建立一个空的segment list用来储存有效走线
    std::vector<ContestSegment>& routing_segment_list = contest_net.get_routing_segment_list();
    
    // k. 遍历planar_layer_map的每一个元素，即每一个via
    for (auto& [planar_coord, layer_set] : planar_layer_map) {

      // l. 通过set的begin和end迭代器，获取via的两层layer的id
      int low_layer_idx = *layer_set.begin();
      auto layer_set_end = layer_set.end();
      layer_set_end--;
      int high_layer_idx = *layer_set_end;

      // m. 将两组x y 和 layer id输入，得到routing_segment_list的一个元素，表示一根via
      routing_segment_list.emplace_back(ContestCoord(planar_coord.first, planar_coord.second, low_layer_idx),
                                        ContestCoord(planar_coord.first, planar_coord.second, high_layer_idx));
    }

    // n. 写入via之后，开始写入平面的guide，因此遍历每一条guide
    for (ContestGuide& contest_guide : contest_net.get_guide_list()) {

      // 接下来这一段和c, d, e一样
      int layer_idx = layer_name_to_idx_map[contest_guide.get_layer_name()];
      ContestCoord real_lb_coord(contest_guide.get_lb_x() + (single_gcell_x_span / 2), contest_guide.get_lb_y() + (single_gcell_y_span / 2),
                                 layer_idx);
      ContestCoord real_rt_coord(contest_guide.get_rt_x() - (single_gcell_x_span / 2), contest_guide.get_rt_y() - (single_gcell_y_span / 2),
                                 layer_idx);
      ContestCoord grid_lb_coord = getGCellCoord(real_lb_coord);
      ContestCoord grid_rt_coord = getGCellCoord(real_rt_coord);

      // o. 由于现在定义的routing_segment_list是一个vector，所以可能会出现相同的x y id也会写入，因此通过if排除这种情况
      if (grid_lb_coord == grid_rt_coord) {
        // 删除点线段
        continue;
      }

      // p. 将平面线段写入routing_segment_list
      routing_segment_list.emplace_back(grid_lb_coord, grid_rt_coord);
    }
  }
}

// add more
// 实现makeRelativeNetsMap(),IdbInstance->ContestNet
void myContestEvaluation::makeRelativeNetsMap() {
  std::unordered_map<idb::IdbInstance *, std::vector<ContestNet *>>& RelativeNetsMap = _data_manager->get_database()->getRelativeNetsMap();
  // 为每个 IdbInstance 对象在 RelativeNetsMap 中创建一个空的 std::vector<const ContestNet *>，表示与该 IdbInstance 相关的 ContestNet 列表。
  for (idb::IdbInstance* Cell : _data_manager->get_idb_design()->get_instance_list()->get_instance_list()) {
    RelativeNetsMap.emplace(Cell, std::vector<ContestNet *>());
  }
  for (ContestNet &Net : _data_manager->get_database()->get_net_list()) {
    for (ContestPin &Pin : Net.get_pin_list())
      RelativeNetsMap[Pin.get_instance()].emplace_back(&Net);
  }
  // 对于每个 IdbInstance 对象相关联的 ContestNet 对象指针列表，进行排序，并移除重复的指针。
  for (auto &P : RelativeNetsMap) {
    std::sort(P.second.begin(), P.second.end());
    P.second.erase(std::unique(P.second.begin(), P.second.end()), P.second.end());
  }

  // ---------------test code-----------------
  // count计数器，打印 RelativeNetsMap 的前10条记录
  // int count = 0;
  // for (auto &entry : RelativeNetsMap) {
  //   idb::IdbInstance *instance = entry.first;
  //   std::vector<ContestNet *> &nets = entry.second;

  //   std::cout << "Instance: " << instance->get_name() << std::endl;
  //   std::cout << "Connected Nets: ";
  //   for (ContestNet *net : nets) {
  //     std::cout << net->get_net_name() << " ";
  //   }
  //   std::cout << std::endl;

  //   ++count;
  //   if (count >= 10) {
  //     break;
  //   }

  // }
  // ---------------test code-----------------
  
}

bool myContestEvaluation::doEvaluation()
{
  // check overlap
  if (overlapCheckPassed()) {
    std::cout << "Overlap check successful!" << std::endl;
  } else {
    std::cout << "Overlap check failed!" << std::endl;
  }

  // check connectivity
  if (connectivityCheckPassed()) {
    std::cout << "Connectivity check successful!" << std::endl;
  } else {
    std::cout << "Connectivity check failed!" << std::endl;
  }

  // check overflow
  if (overflowCheckPassed()) {
    std::cout << "Overflow check successful!" << std::endl;
  } else {
    std::cout << "Overflow check failed!" << std::endl;
  }
  printInstanceArea();
  printWnsAndTNS();
  return true;
}

bool myContestEvaluation::overlapCheckPassed()
{
  int single_gcell_area = _data_manager->get_database()->get_single_gcell_area();

  std::map<ContestCoord, int, CmpContestCoord> coord_used_area_map;
  for (ContestInstance& contest_instance : _data_manager->get_database()->get_instance_list()) {
    ContestCoord& grid_coord = contest_instance.get_grid_coord();
    if ((coord_used_area_map[grid_coord] + contest_instance.get_area()) > single_gcell_area) {
      std::cout << "Overlap GCell: " << grid_coord.get_x() << grid_coord.get_y() << grid_coord.get_layer_idx() << std::endl;
      return false;
    } else {
      coord_used_area_map[grid_coord] += contest_instance.get_area();
    }
  }
  return true;
}

bool myContestEvaluation::connectivityCheckPassed()
{
  int net_count = 0;
  int disconnected_net_count = 0;
  bool check_result = true;
  for (ContestNet& contest_net : _data_manager->get_database()->get_net_list()) {
    net_count++;
    if (net_count == 60001) {
      std::cout << "Check Point!" << std::endl;
    }
    std::vector<ContestCoord> key_coord_list;
    for (ContestPin& contest_pin : contest_net.get_pin_list()) {
      key_coord_list.push_back(contest_pin.get_grid_coord());
    }
    if (!ContestUtil::passCheckingConnectivity(key_coord_list, contest_net.get_routing_segment_list())) {
      std::cout << "Disconnected Net: " << contest_net.get_net_name() << std::endl;
      disconnected_net_count++;
      check_result = false;
    }
  }

  std::cout << "Disconnected Net Count: " << disconnected_net_count << "/" << net_count << std::endl;

  return check_result;
}

bool myContestEvaluation::overflowCheckPassed()
{
  // 1. 初始化和数据准备
  int overflow_gcell_count = 0;
  bool check_result = true;
  int max_overflow = 0;
  //// 获取每层GCell到capacity的容量
  std::map<int, int>& layer_gcell_supply_map = _data_manager->get_database()->get_layer_gcell_supply_map();
  //// 用于记录每个layer overflow了多少个Gcell
  std::map<int, int> layer_to_overflow_map;
  //// 用于记录每个坐标的demand
  std::map<ContestCoord, int, CmpContestCoord> coord_demand_map;

  // 2. 遍历所有网线Net，和布线线段Routing Segment
  for (ContestNet& contest_net : _data_manager->get_database()->get_net_list()) {
    //// 建立一个坐标的set，其中排序方式根据CmpContestCoord，按先x，再y的顺序排列
    std::set<ContestCoord, CmpContestCoord> coord_set;
    for (ContestSegment& routing_segment : contest_net.get_routing_segment_list()) {
      //// 读取一个segment的左下角和右上角坐标，包括x, y和layer ID
      int lb_x = routing_segment.get_first().get_x();
      int lb_y = routing_segment.get_first().get_y();
      int lb_layer_idx = routing_segment.get_first().get_layer_idx();

      int rt_x = routing_segment.get_second().get_x();
      int rt_y = routing_segment.get_second().get_y();
      int rt_layer_idx = routing_segment.get_second().get_layer_idx();

      //// 如果左下角和右上角的layer ID不同，意味着这是一个VIA，就直接跳过
      if (lb_layer_idx != rt_layer_idx) {
        continue;
      }
      //// 第三个for循环实际上没用，因为已经是同一层了
      //// 遍历segment经过的每一个点
      for (int x = lb_x; x <= rt_x; x++) {
        for (int y = lb_y; y <= rt_y; y++) {
          for (int layer_idx = lb_layer_idx; layer_idx <= rt_layer_idx; layer_idx++) {
            //// 判断条件
            //// 由于一个route的起点和终点定义为Gcell的中心坐标，overflow考虑的是完整穿过线，
            //// 所以不考虑头尾两点，中间的点会加到coord_set里面
            if ((lb_x != rt_x && (x == lb_x || x == rt_x)) || (lb_y != rt_y && (y == lb_y || y == rt_y))) {
              continue;
            }
            //// 因为coord_set位于第一个for循环中，因此储存了一个Net上经过的所有coord
            coord_set.insert(ContestCoord(x, y, layer_idx));
          }
        }
      }
    }

    // 3. 计算需求和检查溢出
    for (const ContestCoord& coord : coord_set) {
      //// coord_demand_map刚开始是空的，如果没有coord这个key，对int这个value会默认返回一个0，并且插入coord,0
      //// 这个键值对
      //// 因此判断针对给定的coord，其demand（int value的数字）大于capacity
      //// 因为 coord_demand_map[coord] += 1 这一行写在if之后，所以if中的==本质上是是否判断大于capacity
      if (coord_demand_map[coord] == layer_gcell_supply_map[coord.get_layer_idx()]) {
        //// 一旦等于capacity，那就print是哪一个Gcell出错
        std::cout << "Overflow GCell: (" << coord.get_x() << "," << coord.get_y() << "," << coord.get_layer_idx() << ")" << std::endl;
        //// 输出检查错误
        check_result = false;
        //// Overflow的Gcell 加一个
        overflow_gcell_count++;
        //// 该layer overflow的Gcell数量 加一个
        layer_to_overflow_map[coord.get_layer_idx()]++;
      }

      //// 占用demand的coord数量加一个
      coord_demand_map[coord] += 1;

      //// 输出overflow的值
      auto overflow = coord_demand_map[coord] - layer_gcell_supply_map[coord.get_layer_idx()];
      max_overflow = std::max(max_overflow, overflow);
    }
  }
  // // *********************测试坐标总数************************** //
  // int totalValueSum = 0;
  // for (const auto& pair : coord_demand_map) {
  //     totalValueSum += pair.second;
  // }
  // std::cout << "Total number of coordinates: " << totalValueSum << std::endl;
  // // *********************测试完成******************************=//
  //// 输出结果
  std::cout << "Max Overflow: " << max_overflow << std::endl;
  // output layer to overflow map
  std::cout << "Layer to Overflow Map: " << std::endl;
  for (auto& item : layer_to_overflow_map) {
    std::cout << item.first << ": " << item.second << std::endl;
  }

  return check_result;
}

void myContestEvaluation::printInstanceArea()
{
  uint64_t instance_area = 0;
  for (ContestInstance& instance : _data_manager->get_database()->get_instance_list()) {
    instance_area += instance.get_area();
  }

  std::cout << "total instance area: " << instance_area << std::endl;
}

void myContestEvaluation::printWnsAndTNS()
{
  int single_gcell_x_span = _data_manager->get_database()->get_single_gcell_x_span();
  int single_gcell_y_span = _data_manager->get_database()->get_single_gcell_y_span();
  /////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////
  struct RCPin
  {
    RCPin() = default;
    RCPin(ContestCoord coord, bool is_real_pin, std::string pin_name)
    {
      _coord = coord;
      _is_real_pin = is_real_pin;
      _pin_name = pin_name;
    }
    RCPin(ContestCoord coord, bool is_real_pin, int fake_pin_id)
    {
      _coord = coord;
      _is_real_pin = is_real_pin;
      _fake_pin_id = fake_pin_id;
    }
    ~RCPin() = default;

    ContestCoord _coord;
    bool _is_real_pin = false;
    std::string _pin_name;
    int _fake_pin_id;
  };
  using RCPinSegment = std::pair<RCPin, RCPin>;
  // 定义了一个 lambda 表达式getRCSegmentList。
  auto getRCSegmentList = [](std::map<ContestCoord, std::vector<std::string>, CmpContestCoord>& coord_real_pin_map,
                             std::vector<ContestSegment>& routing_segment_list) {
    std::vector<RCPinSegment> rc_segment_list;
    // 生成线长为0的线段
    for (auto& [coord, real_pin_list] : coord_real_pin_map) {
      for (size_t i = 1; i < real_pin_list.size(); i++) {
        RCPin first_rc_pin(coord, true, real_pin_list[i - 1]);
        RCPin second_rc_pin(coord, true, real_pin_list[i]);
        rc_segment_list.emplace_back(first_rc_pin, second_rc_pin);
      }
    }
    // 构建coord_fake_pin_map
    std::map<ContestCoord, int, CmpContestCoord> coord_fake_pin_map;
    int fake_id = 0;
    for (ContestSegment& routing_segment : routing_segment_list) {
      ContestCoord& first_coord = routing_segment.get_first();
      ContestCoord& second_coord = routing_segment.get_second();

      // 检查其起始坐标和结束坐标是否存在于 coord_real_pin_map 中，如果不存在，则将其添加到 coord_fake_pin_map 中，并为其分配一个唯一的整数标识符（fake_id）。
      if (!ContestUtil::exist(coord_real_pin_map, first_coord) && !ContestUtil::exist(coord_fake_pin_map, first_coord)) {
        coord_fake_pin_map[first_coord] = fake_id++;
      }
      if (!ContestUtil::exist(coord_real_pin_map, second_coord) && !ContestUtil::exist(coord_fake_pin_map, second_coord)) {
        coord_fake_pin_map[second_coord] = fake_id++;
      }
    }
    // 将routing_segment_list生成rc_segment_list
    for (ContestSegment& routing_segment : routing_segment_list) {
      ContestCoord& first_coord = routing_segment.get_first();
      ContestCoord& second_coord = routing_segment.get_second();

      RCPin first_rc_pin;
      if (ContestUtil::exist(coord_real_pin_map, first_coord)) {
        first_rc_pin = RCPin(first_coord, true, coord_real_pin_map[first_coord].front());
      } else if (ContestUtil::exist(coord_fake_pin_map, first_coord)) {
        first_rc_pin = RCPin(first_coord, false, coord_fake_pin_map[first_coord]);
      } else {
        std::cout << "The coord is not exist!" << std::endl;
      }
      RCPin second_rc_pin;
      if (ContestUtil::exist(coord_real_pin_map, second_coord)) {
        second_rc_pin = RCPin(second_coord, true, coord_real_pin_map[second_coord].front());
      } else if (ContestUtil::exist(coord_fake_pin_map, second_coord)) {
        second_rc_pin = RCPin(second_coord, false, coord_fake_pin_map[second_coord]);
      } else {
        std::cout << "The coord is not exist!" << std::endl;
      }
      rc_segment_list.emplace_back(first_rc_pin, second_rc_pin);
    }
    return rc_segment_list;
  };
  /////////////////////////////////////////////////////////////
  ista::TimingEngine* timing_engine = ista::TimingEngine::getOrCreateTimingEngine();
  timing_engine->set_num_threads(8);
  timing_engine->buildGraph();
  timing_engine->initRcTree();

  ista::Netlist* sta_netlist = timing_engine->get_netlist();

  for (ContestNet& net : _data_manager->get_database()->get_net_list()) {
    // coord_real_pin_map
    std::map<ContestCoord, std::vector<std::string>, CmpContestCoord> coord_real_pin_map;
    for (ContestPin& pin : net.get_pin_list()) {
      for (std::string& pin_name : pin.get_contained_pin_list()) {
        ContestCoord gcell_real_coord(pin.get_grid_coord().get_x() * single_gcell_x_span,
                                      pin.get_grid_coord().get_y() * single_gcell_y_span);
        coord_real_pin_map[gcell_real_coord].push_back(pin_name);
        // 用的真实坐标。
      }
    }
    // routing_segment_list
    std::vector<ContestSegment> routing_segment_list;
    if (net.get_routing_segment_list().empty()) {
      // std::set<ContestCoord, CmpContestCoord> coord_set;
      // for (ContestPin& pin : net.get_pin_list()) {
      //   coord_set.insert(pin.get_real_coord());
      // }
      // if (coord_set.size() != 1) {
      //   std::cout << "coord_set.size() != 1" << std::endl;
      // }
      // net.get_routing_segment_list().emplace_back(*coord_set.begin(), *coord_set.begin());
    } else {
      for (ContestSegment& grid_segment : net.get_routing_segment_list()) {
        ContestCoord first_coord(grid_segment.get_first().get_x() * single_gcell_x_span,
                                 grid_segment.get_first().get_y() * single_gcell_y_span);
        ContestCoord second_coord(grid_segment.get_second().get_x() * single_gcell_x_span,
                                  grid_segment.get_second().get_y() * single_gcell_y_span);
        if (first_coord == second_coord) {
          continue;
        }
        routing_segment_list.emplace_back(first_coord, second_coord); // 不考虑通孔。
      }
    }
    // 构建RC-tree
    ista::Net* ista_net = sta_netlist->findNet(net.get_net_name().c_str());
    for (RCPinSegment& segment : getRCSegmentList(coord_real_pin_map, routing_segment_list)) {
      // 捕获列表 [timing_engine, sta_netlist, ista_net] 传递给 lambda 表达式。
      // 定义了一个 lambda 表达式 getRctNode，它接受一个 RCPin 类型的参数 rc_pin。该 lambda 表达式用于获取一个 RCPin 对象对应的时序节点。
      auto getRctNode = [timing_engine, sta_netlist, ista_net](RCPin& rc_pin) {
        ista::RctNode* rct_node = nullptr;
        if (rc_pin._is_real_pin) {
          ista::DesignObject* pin_port = nullptr;
          auto pin_port_list = sta_netlist->findPin(rc_pin._pin_name.c_str(), false, false);
          if (!pin_port_list.empty()) {
            pin_port = pin_port_list.front();
          } else {
            pin_port = sta_netlist->findPort(rc_pin._pin_name.c_str());
          }
          rct_node = timing_engine->makeOrFindRCTreeNode(pin_port);
        } else {
          rct_node = timing_engine->makeOrFindRCTreeNode(ista_net, rc_pin._fake_pin_id);
        }
        return rct_node;
      };
      RCPin& first_rc_pin = segment.first;
      RCPin& second_rc_pin = segment.second;

      int distance = ContestUtil::getManhattanDistance(first_rc_pin._coord, second_rc_pin._coord);
      int unit = dmInst->get_idb_builder()->get_def_service()->get_design()->get_units()->get_micron_dbu();
      std::optional<double> width = std::nullopt;
      double cap = dynamic_cast<ista::TimingIDBAdapter*>(timing_engine->get_db_adapter())->getCapacitance(3, distance / 1.0 / unit, width);
      double res = dynamic_cast<ista::TimingIDBAdapter*>(timing_engine->get_db_adapter())->getResistance(3, distance / 1.0 / unit, width);

      ista::RctNode* first_node = getRctNode(first_rc_pin);
      ista::RctNode* second_node = getRctNode(second_rc_pin);
      timing_engine->makeResistor(ista_net, first_node, second_node, res);
      timing_engine->incrCap(first_node, cap / 2);
      timing_engine->incrCap(second_node, cap / 2);
    }
    timing_engine->updateRCTreeInfo(ista_net);
  }
  timing_engine->updateTiming();
  // timing_engine->reportTiming();
  /////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////

  const char* master_clock_name = "CLK_osc_in";
  time_t time1 = time(nullptr);
  double wns = timing_engine->get_ista()->getWNS(master_clock_name, AnalysisMode::kMax);
  double tns = timing_engine->get_ista()->getTNS(master_clock_name, AnalysisMode::kMax);
  // TODO calc score
  std::cout << "wns: " << wns << std::endl;
  std::cout << "tns: " << tns << std::endl;

  
  time_t time2 = time(nullptr);
  double time_diff = difftime(time2, time1);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;

  // demo
  std::cout << " ---------------demo-----------------" << std::endl;
  auto WNS = timing_engine->reportWNS(master_clock_name, AnalysisMode::kMax);
  std::cout << "WNS: " << WNS << std::endl;
  time_t time3 = time(nullptr);
  time_diff = difftime(time3, time2);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;
  auto TNS = timing_engine->reportTNS(master_clock_name, AnalysisMode::kMax);
  std::cout << "TNS: " << TNS << std::endl;
  time_t time4 = time(nullptr);
  time_diff = difftime(time4, time3);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;

  auto arrive_time = timing_engine->reportAT("placeFE_OFC47_FE_OFN0_rst_core_n:X", AnalysisMode::kMax, TransType::kFall);
  std::cout << "arrive_time: " << *arrive_time << std::endl;
  time_t time5 = time(nullptr);
  time_diff = difftime(time5, time4);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;
  auto req_time = timing_engine->reportRT("placeFE_OFC47_FE_OFN0_rst_core_n:X", AnalysisMode::kMax, TransType::kFall);
  std::cout << "req_time: " << *req_time << std::endl;
  time_t time6 = time(nullptr);
  time_diff = difftime(time6, time5);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;

  auto slew = timing_engine->reportSlew("placeFE_OFC47_FE_OFN0_rst_core_n:X", AnalysisMode::kMax, TransType::kRise);
  std::cout << "slew: " << slew << std::endl;
  time_t time7 = time(nullptr);
  time_diff = difftime(time7, time6);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;
  auto slack = timing_engine->reportSlack("placeFE_OFC47_FE_OFN0_rst_core_n:X", AnalysisMode::kMax, TransType::kRise);
  std::cout << "slack: " << *slack << std::endl;
  time_t time8 = time(nullptr);
  time_diff = difftime(time8, time7);
  std::cout << "time_diff: " << time_diff << "s" << std::endl;
}

void myContestEvaluation::makeGridList()
{
  int32_t X_number;
  int32_t Y_number;
  std::vector<Grids>& contest_grid_list = _data_manager->get_database()->get_grid_list();
  std::unordered_map<ContestCoord, SingleGcellInfo, std::hash<ContestCoord>>& contest_singleGcell_map = _data_manager->get_database()->get_singleGcell_map();
  std::map<ContestCoord, int, CmpContestCoord>& contest_coord_used_area_map = _data_manager->get_database()->get_coord_used_area_map();

  // Gcell information, only two elements
  for (idb::IdbGCellGrid* idb_grid : _data_manager->get_idb_layout()->get_gcell_grid_list()->get_gcell_grid_list()) {
    Grids contest_gird;
    contest_gird.contest_set_direction(idb_grid->get_direction());
    contest_gird.contest_set_start(idb_grid->get_start());
    contest_gird.contest_set_num(idb_grid->get_num());
    contest_gird.contest_set_space(idb_grid->get_space());
    contest_grid_list.push_back(contest_gird);

    if (contest_gird.contest_get_direction() == idb::IdbTrackDirection::kDirectionX) 
    {
      X_number = contest_gird.contest_get_num();
      _data_manager->get_database()->contest_set_xnum(contest_gird.contest_get_num());
    } 
    else if (contest_gird.contest_get_direction() == idb::IdbTrackDirection::kDirectionY) 
    {
      Y_number = contest_gird.contest_get_num();
      _data_manager->get_database()->contest_set_ynum(contest_gird.contest_get_num()); 
    }
  }

  // Establish single Gcell list
  int layer_number = 0;
  for (idb::IdbLayer* idb_layer : _data_manager->get_idb_layout()->get_layers()->get_layers()) {
    if (idb_layer->is_routing()) {
      layer_number++;
    }
  }
  _data_manager->get_database()->contest_set_layernum(layer_number);

  // std::cout << "X_number=" << X_number << ", Y_number=" << Y_number << std::endl;
  for (int x = 0; x < X_number; x++) {
    for (int y = 0; y < Y_number; y++) {
      for (int Layer_id = 0; Layer_id < layer_number; Layer_id++) {
        
        ContestCoord gcell_coord(x, y, Layer_id);
        SingleGcellInfo contest_singleGcell(gcell_coord);
        contest_singleGcell.set_cell_capacity(_data_manager->get_database()->get_layer_gcell_supply_map()[Layer_id]);
        // 将SingleGcellInfo添加到map中
        contest_singleGcell_map[gcell_coord] = contest_singleGcell;
      }
    }
  }

  // Compute the demand based on iEDA overflow test function

  Route Route_tmp(_data_manager);

  for (ContestNet& contest_net : _data_manager->get_database()->get_net_list()) {
    for (ContestSegment& routing_segment : contest_net.get_routing_segment_list()) {
      int lb_x = routing_segment.get_first().get_x();
      int lb_y = routing_segment.get_first().get_y();
      int lb_layer_idx = routing_segment.get_first().get_layer_idx();

      int rt_x = routing_segment.get_second().get_x();
      int rt_y = routing_segment.get_second().get_y();
      int rt_layer_idx = routing_segment.get_second().get_layer_idx();

      if (lb_layer_idx != rt_layer_idx) {
        continue;
      }

      for (int x = lb_x; x <= rt_x; x++) {
        for (int y = lb_y; y <= rt_y; y++) {
          for (int layer_idx = lb_layer_idx; layer_idx <= rt_layer_idx; layer_idx++) {
            if ((lb_x != rt_x && (x == lb_x || x == rt_x)) || (lb_y != rt_y && (y == lb_y || y == rt_y))) {
              continue;
            }
            // Compute demand
            try {
                SingleGcellInfo& cell = Route_tmp.FindCellInMap(x, y, layer_idx);
                cell.addDemand(1);
                // std::cout << "One more demand in SingleGcell at (x=" << x << ", y=" << y << ", layerID=" << layer_idx << ")" << std::endl;
            } catch (const std::exception& e) {
                std::cerr << "Exception caught for (x=" << x << ", y=" << y << ", layerID=" << layer_idx << "), " << e.what() << std::endl;
            }

          }
        }
      }
    }
  }

  // zhihui add more
  for (idb::IdbInstance* idb_instance : _data_manager->get_idb_design()->get_instance_list()->get_instance_list()) {
    int single_gcell_area = _data_manager->get_database()->get_single_gcell_area();
    ContestCoord coord(idb_instance->get_bounding_box()->get_middle_point_x(), idb_instance->get_bounding_box()->get_middle_point_y(), 0);
    ContestCoord grid_coord = getGCellCoord(coord);

    int idb_instance_area = idb_instance->get_cell_master()->get_width() * idb_instance->get_cell_master()->get_height();

    if ((contest_coord_used_area_map[grid_coord] + idb_instance_area) > single_gcell_area) {
      std::cout << "Overlap GCell: " << grid_coord.get_x() << grid_coord.get_y() << grid_coord.get_layer_idx() << std::endl;
    } else {
      contest_coord_used_area_map[grid_coord] += idb_instance_area;
    }
  }

} // makeGridList


}  // namespace ieda_contest